package com.cx.common.utils;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.math.BigDecimal;
import java.util.*;

/**
 * 
 * @Author:cxy
 *
 */
public class Tools {

	private static final Logger log = LoggerFactory.getLogger(Tools.class);

	private Tools() {
	}

	public static final String DELIMITER_INNER_ITEM = "_";
	public static final String DELIMITER_INNER_ITEM1 = ":";
	public static final String DELIMITER_INNER_ITEM2 = ",";
	public static final String DELIMITER_BETWEEN_ITEMS = "|";
	public static final String DELIMITER_BETWEEN_ITEMS2 = "#";
	public static final String ARGS_DELIMITER = " ";
	public static final String ARGS_ITEMS_DELIMITER = "\\|";

	/**
	 * 对象转换成字节数组
	 * 
	 * @param obj
	 *            对象
	 * @return byte[]
	 */
	public static byte[] object2ByteArray(Object obj) {
		if (obj == null) {
			return null;
		}

		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			(new ObjectOutputStream(bos)).writeObject(obj);

			return bos.toByteArray();
		} catch (IOException ex) {
			log.error("failed to serialize obj", ex);
			return null;
		}

	}

	/**
	 * 字节数组转换成对象
	 * 
	 * @param buffer
	 * @return Object
	 */
	public static Object byteArray2Object(byte[] buffer) {
		if (buffer == null || buffer.length == 0) {
			return null;
		}

		ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
		ObjectInputStream ois = null;
		try {
			ois = new ObjectInputStream(bais);
			return ois.readObject();
		} catch (Exception ex) {
			log.error("failed to deserialize obj", ex);
			return null;
		} finally {
			try {
				if (ois != null) {
					ois.close();
				}
			} catch (Exception e) {
			}
			try {
				bais.close();
			} catch (Exception e) {
			}
		}
	}

	/**
	 * 把以|_分割的字符串分解成数组
	 * 
	 * @param delimiterString
	 * @return List<String[]>
	 */
	public static List<String[]> delimiterString2Array(String delimiterString) {
		if (delimiterString == null || delimiterString.trim().length() == 0) {
			return null;
		}

		String[] ss = delimiterString.trim().split(Tools.ARGS_ITEMS_DELIMITER);
		if (ss != null && ss.length > 0) {
			List<String[]> list = new ArrayList<String[]>(ss.length);
			for (int i = 0; i < ss.length; i++) {
				list.add(ss[i].split(Tools.DELIMITER_INNER_ITEM));
			}
			return list;
		}
		return null;
	}

	/**
	 * 把以|_分割的字符串分解成HashMap,键位为字符串的0下标数值
	 * 
	 * @param delimiterString
	 * @return Map<String,String[]>
	 */
	public static Map<String, String[]> delimiterString2Map(String delimiterString) {
		Map<String, String[]> map = new HashMap<String, String[]>();
		if (delimiterString == null || delimiterString.trim().length() == 0) {
			return map;
		}

		String[] ss = delimiterString.trim().split(Tools.ARGS_ITEMS_DELIMITER);
		if (ss != null && ss.length > 0) {
			for (int i = 0; i < ss.length; i++) {
				String[] str = ss[i].split(Tools.DELIMITER_INNER_ITEM);
				if (str.length > 0) {
					map.put(str[0], str);
				}
			}
			return map;
		}
		return map;
	}

	/**
	 * 把子项集合转换成以|_分割的字符串
	 * 
	 * @param delimiterString
	 * @return Map<String,String[]>
	 */
	public static String delimiterCollection2String(Collection<String[]> collection) {
		if (collection == null || collection.isEmpty()) {
			return StringUtils.EMPTY;
		}

		StringBuilder subContent = new StringBuilder();
		for (String[] strings : collection) {
			if (strings == null || strings.length == 0) {
				continue;
			}
			for (int i = 0; i < strings.length; i++) {
				subContent.append(strings[i]).append(Tools.DELIMITER_BETWEEN_ITEMS);
			}
			subContent.setLength(subContent.length() - 1);
			subContent.append(Tools.DELIMITER_INNER_ITEM);
		}
		return subContent.toString();
	}

	/**
	 * 把子项数组转换成以_分割的字符串
	 * 
	 * @param subArray
	 *            子项数组
	 * @return String
	 */
	public static String array2DelimiterString(Object[] subArray) {
		if (subArray == null || subArray.length == 0) {
			return StringUtils.EMPTY;
		}
		StringBuilder subContent = new StringBuilder();
		for (int i = 0; i < subArray.length; i++) {
			subContent.append(subArray[i]).append(Tools.DELIMITER_INNER_ITEM);
		}
		int length = subContent.length();
		if (length > 0) {
			subContent.setLength(length - 1);
		}
		return subContent.toString();
	}

	/**
	 * 把List中的子项数组转换成以|_分割的字符串
	 * 
	 * @param subArrayList
	 *            , 子项数组集合
	 * @return String
	 */
	public static String listArray2DelimiterString(List<String[]> subArrayList) {
		if (subArrayList == null || subArrayList.isEmpty()) {
			return StringUtils.EMPTY;
		}

		StringBuilder subContent = new StringBuilder();
		for (String[] strings : subArrayList) {
			if (strings == null || strings.length == 0) {
				continue;
			}
			for (int i = 0; i < strings.length; i++) {
				subContent.append(strings[i]).append(Tools.DELIMITER_BETWEEN_ITEMS);
			}
			subContent.setLength(subContent.length() - 1);
			subContent.append(Tools.DELIMITER_INNER_ITEM);
		}
		return subContent.toString();
	}

	/**
	 * 提供精确的小数位四舍五入处理。
	 * 
	 * @param v
	 *            需要四舍五入的数字
	 * @param scale
	 *            小数点后保留几位
	 * @return 四舍五入后的结果
	 */
	public static double round(double v, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		BigDecimal b = new BigDecimal(Double.toString(v));
		BigDecimal one = new BigDecimal("1");
		return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	public static double roundDown(double v, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		BigDecimal b = new BigDecimal(Double.toString(v));
		BigDecimal one = new BigDecimal("1");
		return b.divide(one, scale, BigDecimal.ROUND_DOWN).doubleValue();
	}

	/**
	 * 提供精确的小数位向上四舍五入处理。
	 * 
	 * @param v
	 * @param scale
	 * @return
	 */
	public static double roundUp(double v, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		BigDecimal b = new BigDecimal(Double.toString(v));
		BigDecimal one = new BigDecimal("1");
		return b.divide(one, scale, BigDecimal.ROUND_UP).doubleValue();
	}

	/**
	 * 提供精确的小数位向上四舍五入处理。
	 * 
	 * @param v1
	 * @param v2
	 * @param scale
	 * @return
	 */
	public static double divideAndRoundUp(double v1, double v2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}

		BigDecimal bd1 = new BigDecimal(v1);
		BigDecimal bd2 = new BigDecimal(v2);

		return bd1.divide(bd2, scale, BigDecimal.ROUND_UP).doubleValue();
	}

	public static double divideAndRoundDown(double v1, double v2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}

		BigDecimal bd1 = new BigDecimal(v1);
		BigDecimal bd2 = new BigDecimal(v2);

		return bd1.divide(bd2, scale, BigDecimal.ROUND_DOWN).doubleValue();
	}

	/**
	 * 将制定的键值放入map (其中 Map<?, List<?>>)
	 * 
	 * @param map
	 *            Map<?, List<?>>
	 * @param key
	 * @param value
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void add2MapList(Map map, Object key, Object value) {
		if (map != null && key != null) {
			List list = (List) map.get(key);
			if (list == null) {
				list = new ArrayList(0);
				map.put(key, list);
			}
			list.add(value);
		}
	}

	/**
	 * 连接对象成字符串
	 * 
	 * @param args
	 * @return
	 */
	public static String join(String separator, Object... args) {
		if (args == null || args.length <= 0) {
			return StringUtils.EMPTY;
		}
		StringBuilder builder = new StringBuilder();
		for (Object arg : args) {
			builder.append(arg).append(separator);
		}
		int length = builder.length();
		if (length > 0) {
			builder.setLength(length - 1);
		}
		return builder.toString();
	}

	public static void main(String[] args) throws Exception {
		// String test = "nishizhu";
		//
		// String encode = new BASE64Encoder().encode(test.getBytes());
		//
		// System.out.println("orign: " + test);
		// System.out.println("encode: " + encode );
		//
		// byte[] decode = new BASE64Decoder().decodeBuffer(encode);
		//
		// System.out.println("decode: " + new String(decode));

		// @SuppressWarnings("unused")
		// List<String[]> st =
		// delimiterString2Array("0_1_1060_10|0_2_1061_10|0_3_1062_10|");
		// List<String[]> arrayList = new ArrayList<String[]>();
		// arrayList.add(new String[] { "1", "2", "3" });
		// arrayList.add(new String[] { "2", "2", "3" });
		// arrayList.add(new String[] { "3", "2", "3" });
		// arrayList.add(new String[] { "4", "2", "3" });
		// arrayList.add(new String[] { "5", "2", "3" });
		// arrayList.add(new String[] { "6", "2", "3" });
		// String str = listArray2DelimiterString(arrayList);
		// logger.debug("str: {}" , str);

		// long start = System.currentTimeMillis();
		// for (int i = 0; i < 10000000; i++) {
		// SecureRandom.getInstance("SHA-256").nextInt(1000);
		// }
		// long end = System.currentTimeMillis();
		// System.err.println("SecureRandom getInstance: "+ (end - start));
		//
		long start = System.currentTimeMillis();
		// for (int i = 0; i < 10000000; i++) {
		// new SecureRandom().nextInt(1000);
		// }
		long end = System.currentTimeMillis();
		System.err.println("SecureRandom: " + (end - start));

		start = System.currentTimeMillis();
		for (int i = 0; i < 100; i++) {
			// System.err.println(RANDOM.nextInt(1000));
		}
		end = System.currentTimeMillis();
		System.err.println("RANDOM:" + (end - start));
	}

}
